/**
 * 给定一个序列<t, x>
 * 当t=1，表示可以拿到一个x类型的药，当然也可以不拿
 * 当t=2，表示碰到一个x类型的怪物，必须使用x类型的要消灭之，否则失败
 * 给定序列，问能否成功
 * 在成功的基础上，还要求时时刻刻尽可能持有的药的数量最少
 * 最后输出最少，以及方案
 * 令need为所需的药，have为可以有的药
 * 反向遍历：
 *     每碰到一个怪物，need[x]加加
 *     每碰到一种药，如果have不够，则要拿该药
 * 也就是说对每一种必须的药，尽可能的推迟入手的时间，等价于尽可能的减少持有的时间段
 * 如此可以保证持有的总量最少，因为每一种药都是当前时刻必须的，没有多余的
 * 然后再正向跑一遍，得到答案
 */
#include <bits/stdc++.h>
using namespace std;

#include <bits/extc++.h>
using namespace __gnu_pbds;

using llt = long long;
using pii = pair<int, int>;
using vi = vector<int>;
using vvi = vector<vi>;

int N;
vector<pii> A;

vi Ans;

void proc(){
    Ans.clear(); Ans.reserve(N);
    vi need(N + 1, 0);
    vi have(N + 1, 0);
    for(int i=N-1;i>=0;--i){
        const auto & p = A[i];
        if(1 == p.first){
            if(have[p.second] < need[p.second]){
                Ans.push_back(1);
                ++have[p.second];
            }else{
                Ans.push_back(0);
            }
        }else if(2 == p.first){
            ++need[p.second];
        }else{
            assert(0);
        }
    }

    reverse(Ans.begin(), Ans.end());
    
    int k = 0;
    int ans = 0;
    int ret = 0;
    need.assign(N + 1, 0);
    have.assign(N + 1, 0);
    for(const auto & p : A){
        if(1 == p.first){
            if(1 == Ans[k++]){
                ++have[p.second];
                ret = max(ret, ++ans);                
            }
        }else if(2 == p.first){
            ++need[p.second];
            if(have[p.second] < need[p.second]){
                return (void)(cout << -1 << endl);
            }else{
                --ans;
            }
        }  
    }
    cout << ret << endl;
    for(auto i : Ans)cout << i << " ";
    cout << endl;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("z.txt", "r", stdin);
#endif
    ios::sync_with_stdio(false);cin.tie(nullptr);cout.tie(0);
    int nofkase = 1;
    // cin >> nofkase;
    while(nofkase--){
        cin >> N;
        A.assign(N, {});
        for(auto & p : A) cin >> p.first >> p.second;
        proc();
    }
    return 0;
}